/**
 * File: VirtualAdvisor.java
 * Author: Ben Stutsky
 * Team: Bob-omb Squad
 * Date: 4/18/11
 * Email: stutsky1@umbc.edu
 */
package clientApp;

import java.io.IOException;
import java.util.ArrayList;

import clientSocket.RequestInterpreter;

/**
 * The Virtual Advisor class.
 * This class is the commanding(TRADEMARK) class of the Virtual Advisor application.
 * 
 * 
 */
public class VirtualAdvisor 
{
	private boolean isAdmin	= false;
	private boolean loggedIn = false;
	private User presentUser = null;
	private static ArrayList<Degree> degrees = new ArrayList<Degree>(); 
	private static Catalog catalog	= new Catalog();
	private static ArrayList<User> users = new ArrayList<User>();
	
	private User verified = null;
	private boolean lastRights = false; 
	
	//
	//Unfinished methods
	//
	public boolean registerAndlogin(String username, String password, String name, String degree)
	{
		for (User u : users) {
			if (u.getName().equals(username)) {
				return false;
			}
		}
		
		if (degree.equals("Computer Science(CS) Major")) {
			degree = "Computer Science Major";
		} else if (degree.equals("Information Systems(IS) Major")) {
			degree = "Information Systems Major";
		} else if (degree.equals("CS/IS Double Major")) {
			degree = "Computer Science and Information Systems";
		} else if (degree.equals("CS Minor")) {
			degree = "Information Systems with Computer Science Minor";
		} else {
			degree = "Undecided.";
		}
		
		Student newUser = new Student(username, password, name, ProjectConstants.getDegreeInt(degree));
		userLogin(newUser, false);
		return true;
		/*
		try 
		{
			if(checkUser(username, password) == false)
			{
				//code to make new user
				User newUser = null;
				userLogin(newUser, false);
				
				return true;
			}
		} 
		catch (IOException e) 
		{
			//double check me
			return false;
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;*/
	}
	//
	//
	//
	
	//
	// degree methods
	//
	public boolean doesFullPlanCompleteDegree(String planName)
	{
		if(!isAdmin && loggedIn)
		{
			Plan myPlan = this.getPlan(planName);
			Degree myDegree = getPresentUsersDegree();
			
			return DegreeAudit.isComplete(myDegree, myPlan.getAllCourseRecords(), catalog);
		}
		return false;
	}
	public boolean doesPreviousPlanCompleteDegree(String planName)
	{
		if(!isAdmin && loggedIn)
		{
			Plan myPlan = this.getPlan(planName);
			Degree myDegree = getPresentUsersDegree();
			
			return DegreeAudit.isComplete(myDegree, myPlan.getAllTakenCourseRecords(), catalog);
		}
		return false;
	}
	
	public String analyseFullPlanCompleteDegree(String planName)
	{
		String retString = "";
		
		if(!isAdmin && loggedIn)
		{
			Plan myPlan = this.getPlan(planName);
			Degree myDegree = getPresentUsersDegree();
			
			retString = DegreeAudit.analyseDegree(myDegree, myPlan.getAllCourseRecords(), catalog);
			
			retString += this.getAdditionAuditInformation(planName);
			
		}
		else
		{
			retString = "Either you are an admin or you are not logged in.";
		}
		
		return retString;
	}
	
	public String analysePreviousPlanCompleteDegree(String planName)
	{
		String retString = "";
		if(!isAdmin && loggedIn)
		{
			Plan myPlan = this.getPlan(planName);
			Degree myDegree = getPresentUsersDegree();
			
			retString = DegreeAudit.analyseDegree(myDegree, myPlan.getAllCourseRecords(), catalog);
			
			retString += this.getAdditionAuditInformation(planName);
		}
		else
		{
			retString = "Either you are an admin or you are not logged in.";
		}
		return retString;
	}
	
	private String getAdditionAuditInformation(String planName)
	{
		String retString = "";
		retString += "\n\n";
		retString += "Cumulative GPA So Far: " + this.calculateOverallGPA(planName);
		retString += "\nIs Minimum GPA met: " + this.hasMinGPA(planName);
		retString += "\nCredits Earned: " + this.getCreditsEarned(planName);
		retString += "\nIs minimum credits earned: " + this.hasOneTwentyCredits(planName);
		retString += "\nIs upper level requirements met: " + this.hasFourtyFiveUpperLevelCredits(planName);
		retString += "\n\nIs degree complete: " + this.doesFullPlanCompleteDegree(planName);
		return retString;
	}
	
	private double getCreditsEarned(String planName)
	{
		Plan myPlan = getPlan(planName);
		double sum = 0;
		
		for(Semester sem : myPlan.getSemesters())
		{
			for(String id : sem.getCourseIDs())
			{
				if(catalog.getCourse(id) != null)
					sum += catalog.getCourse(id).getNumCreds();
			}
		}
		return sum;
	}
	
	private Degree getPresentUsersDegree()
	{
		Student me = (Student)presentUser;
		String degreeName = ProjectConstants.getDegreeString(me.getDegree());
		
		for(int i = 0; i != degrees.size(); i++)
		{
			Degree trial = degrees.get(i);
			if(trial.name.compareTo(degreeName) == 0)
			{
				return trial;
			}
		}
		
		return null;
	}
	
	//
	// end degree methods
	//
	
	//
	//User methods
	//
	public boolean checkUser(String username, String password) throws IOException, ClassNotFoundException
	{
		for (User u : users) {
			if ((u.getUsername().equals(username)) && (u.getPassword().equals(password))) {
				verified = u;
				lastRights = RequestInterpreter.getUserType(username) != 1;
				return verified != null;
			}
		}
		
		return false;
/*		
		verified = RequestInterpreter.findUser(username, password);
		lastRights = RequestInterpreter.getUserType(username) != 1;
		return verified != null;*/
	}

	public User getLastUser()
	{
		return verified;
	}

	public boolean lastAccessRights()
	{
		return lastRights;
	}
	
	public String getUsername()
	{
		if(loggedIn)
		{
			return presentUser.getUsername();
		}
		return null;
	}
	
	public String getName()
	{
		if(loggedIn)
		{
			return presentUser.getName();
		}
		return null;
	}
	
	public String getPassword()
	{
		if(loggedIn)
		{
			return presentUser.getPassword();
		}
		return null;
	}
	
	public void userLogin(User newUser, boolean isUserAdmin)
	{
		presentUser = newUser;
		users.add(newUser);
		isAdmin = isUserAdmin;
		loggedIn = true;
	}
	
	public void userLogout()
	{
		presentUser = null;
		isAdmin = false;
		loggedIn = false;
	}
	//
	//
	//end user methods
	//
	//
		
	//
	
	//
	//Constructors
	//
	//
	//for testing
	public VirtualAdvisor()
	{
		ArrayList<Plan> myPlans = new ArrayList<Plan>();
		myPlans.add(new Plan("MEHH"));
		myPlans.add(new Plan("ROFL"));
		myPlans.add(new Plan("NOOB"));
		
		Plan myPlan = new Plan("StutskyPlan");
		
		//Populating the plan
		Semester mySem1 = new Semester(ProjectConstants.FALL, 2009);
		Semester mySem2 = new Semester(ProjectConstants.SPRING, 2010);
		Semester mySem3 = new Semester(ProjectConstants.FALL, 2010);
		Semester mySem4 = new Semester(ProjectConstants.SPRING, 2011);
		
		CourseRecord myCR11 = new CourseRecord("CMSC 201", 'A', "This is my 201. Rofl.");
		CourseRecord myCR12 = new CourseRecord("MATH 151", 'B', "This is my 201. Rofl.");
		CourseRecord myCR13 = new CourseRecord("LANG 1", 'A', "This is my 201. Rofl.");
		CourseRecord myCR14 = new CourseRecord("ENGL 100", 'A', "This is my 201. Rofl.");
		
		CourseRecord myCR21 = new CourseRecord("MATH 221", 'A', "This is my 201. Rofl.");
		CourseRecord myCR24 = new CourseRecord("CMSC 304", 'B', "This is my 201. Rofl.");
		CourseRecord myCR22 = new CourseRecord("CMSC 202", 'A', "This is my 202. Rofl.");
		CourseRecord myCR23 = new CourseRecord("CMSC 203", 'A', "This is my 203. Rofl.");
		CourseRecord myCR25 = new CourseRecord("LANG 2", 'A', "This is my 201. Rofl.");
		
		CourseRecord myCR31 = new CourseRecord("CMSC 313", 'A', "This is my 201. Rofl.");
		CourseRecord myCR32 = new CourseRecord("LANG 3", 'C', "This is my 201. Rofl.");
		CourseRecord myCR33 = new CourseRecord("CHEM 101", 'B', "This is my 201. Rofl.");
		CourseRecord myCR34 = new CourseRecord("CMSC 341", 'B', "This is my 341. Rofl.");
		
		CourseRecord myCR41 = new CourseRecord("CMSC 345", ProjectConstants.NO_GRADE, "This is my 201. Rofl.");
		CourseRecord myCR42 = new CourseRecord("CMSC 331", ProjectConstants.NO_GRADE, "This is my 201. Rofl.");
		CourseRecord myCR43 = new CourseRecord("CHEM 102", ProjectConstants.NO_GRADE, "This is my 201. Rofl.");
		CourseRecord myCR44 = new CourseRecord("STAT 355", ProjectConstants.NO_GRADE, "This is my 201. Rofl.");
		
		mySem1.addCourseRecord(myCR11);
		mySem1.addCourseRecord(myCR12);
		mySem1.addCourseRecord(myCR13);
		mySem1.addCourseRecord(myCR14);
		
		mySem2.addCourseRecord(myCR21);
		mySem2.addCourseRecord(myCR22);
		mySem2.addCourseRecord(myCR23);
		mySem2.addCourseRecord(myCR24);
		mySem2.addCourseRecord(myCR25);
		
		mySem3.addCourseRecord(myCR31);
		mySem3.addCourseRecord(myCR32);
		mySem3.addCourseRecord(myCR33);
		mySem3.addCourseRecord(myCR34);
		
		mySem4.addCourseRecord(myCR41);
		mySem4.addCourseRecord(myCR42);
		mySem4.addCourseRecord(myCR43);
		mySem4.addCourseRecord(myCR44);
		
		myPlan.addSemesterToPlan(mySem1);
		myPlan.addSemesterToPlan(mySem2);
		myPlan.addSemesterToPlan(mySem3);
		myPlan.addSemesterToPlan(mySem4);
		
		myPlans.add(myPlan);
		presentUser = new Student("h", "h", "h", ProjectConstants.CMSC, myPlans);
		isAdmin = false;
		loggedIn = true;
				
		try {
			RequestInterpreter.commence();
			catalog = new Catalog(RequestInterpreter.retrieveCatalog());
			getDegrees();
			users = RequestInterpreter.getAllUsers();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
	}
	
	public VirtualAdvisor(ArrayList<Degree> myDegrees, ArrayList<Course> myCatalog, ArrayList<User> users)
	{
		degrees = myDegrees;
		catalog = new Catalog(myCatalog);
		this.users = users;
	}
	
	public void terminate() {
		try {
			saveData();
			RequestInterpreter.terminate();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//
	//end constructors
	//
	
	//
	//Degree methods
	//
	
	//need to be able to determine how long until earliest graduation
	//relies on degree class
	
	//need to be able to get courses available based on prereqs and avail.
	//
	//end constructors
	//
	
	//
	//Degree methods
	//
	//needs to rely on degree to check for passing grade requirements
	
	public void getDegrees() {
		try	{
			degrees = RequestInterpreter.getDegrees();
		} catch (Exception e) {
			//TODO: Handle this
			e.printStackTrace();
		}
	}
	
	//
	//End Degree Methods
	//
	
	private ArrayList<CourseRecord> getAllCRs(String planName)
	{
		ArrayList<CourseRecord> myCRs = new ArrayList<CourseRecord>();
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			ArrayList<String> titles = myStudent.getAllSemesterTitlesInPlan(planName);
			
			for(int i = 0; i != titles.size(); i++)
			{
				String title = titles.get(i);
				String[] pieces = title.split(" ");
				int season = ProjectConstants.getSeasonInt(pieces[0]);
				int year = Integer.parseInt(pieces[1]);
				ArrayList<CourseRecord> presCRs = myStudent.getCourseRecords(planName, season, year);
				
				for(CourseRecord cr : presCRs)
				{
					myCRs.add(cr);
				}
			}
		}
		else
		{
			return null;
		}
		return myCRs;
	}
	
	private ArrayList<CourseRecord> getAllPreviousCRs(String planName) {
		return((Student)presentUser).getPlanWithName(planName).getAllTakenCourseRecords();
	}
	
	public boolean hasOneTwentyCredits(String planName)
	{
		if(!isAdmin && loggedIn)
		{
			double count = 0;
			ArrayList<CourseRecord> myCRs = getAllCRs(planName);
			for(CourseRecord cr : myCRs)
			{
				Course course = catalog.getCourse(cr.getCourseID());
				if(course != null)
					count += course.getNumCreds();
			}
			if(count >= 120)
			{
				return true;
			}
		}
		return false;
	}
	
	public boolean hasMinGPA(String planName)
	{
		if(!isAdmin && loggedIn)
		{
			if(calculateOverallGPA(planName) >= 2)
			{
				return true;
			}
		}
		return false;
	}
	
	public boolean hasFourtyFiveUpperLevelCredits(String planName)
	{
		ArrayList<CourseRecord> myCRs = getAllCRs(planName);
		
		int count = 0;
		
		for(CourseRecord cr : myCRs)
		{
			String id = cr.getCourseID();
			Course course = catalog.getCourse(id);
			if(course != null)
			{
				String code = course.getCourseCode();
				String[] pieces = code.split(" ");
				if(pieces[1].charAt(0) == '3' || pieces[1].charAt(0) == '4')
				{
					count += course.getNumCreds();
				}
			}
		}
		
		if(count >= 45)
		{
			return true;
		}
		
		return false;
	}
	
	public  boolean hasCompletedCourseThreeTimes(String planName, String courseID) {
		int counter = 0;
		for (CourseRecord takenCourse : getAllPreviousCRs(planName)) {
			if (courseID.equals(takenCourse.getCourseID())) {
				counter++;
			}
		}
		
		return (counter >= 3);
	}
	
	public boolean hasAlreadyTakenThreeTimes(String planName, String courseID)
	{
		int count = 0;
		ArrayList<CourseRecord> myCRs = getAllCRs(planName);
		
		for(CourseRecord cr : myCRs)
		{
			String id = cr.getCourseID();
			
			if(courseID.compareTo(id) == 0)
			{
				count++;
			}	
		}
		
		if(count == 3)
		{
			return true;
		}
		else if(count < 3)
		{
			return false;
		}
		else
		{
			//someone messed up here....
			//taken more than 3 times
			return true;
		}
	}
	
	public boolean isAlreadyTaking(String planName, String courseID)
	{
		ArrayList<CourseRecord> myCRs = getAllCRs(planName);
		
		for(CourseRecord cr : myCRs)
		{
			String id = cr.getCourseID();
			
			if(courseID.compareTo(id) == 0)
			{
				return true;
			}	
		}
		return false;
	}
	
	public String arePrereqsMet(String planName, String courseID)
	{
		String retString = "";
		
		Course testCourse = catalog.getCourse(courseID);
		String[] pre = testCourse.getPrereqs();
		
		if(!isAdmin && loggedIn)
		{
			ArrayList<CourseRecord> myCRs = getAllCRs(planName);
			
			ArrayList<String> notFound = new ArrayList<String>();
			
			for(int i = 0; i != pre.length; i++)
			{
				String p = pre[i];
				boolean found = false;
				for(CourseRecord cr : myCRs)
				{
					String id = cr.getCourseID();
					
					if(id.compareTo(p) == 0)
					{
						found = true;
					}
				}
				if(found != true)
				{
					notFound.add(p);
				}
			}
			
			if(notFound.size() == 0)
			{
				retString = "Everything looks peachy clean here.";
			}
			else
			{
				retString = "You have not met all of the prerequisits for this course!\n";
				retString += "You still need:\n";
				for(String str : notFound)
				{
					retString += str + " ";
				}
			}
		}
		else
		{
			retString = "YOU ARE EITHER AN ADMIN OR NOT LOGGED IN!\nARGSS WHATCHA DOIN TO ME????";	
		}
		
		return retString;
	}
	
	
	
	//
	//
	//End degree methods
	//
	
	//
	//catalog methods
	//
	//
	public ArrayList<Course> getAllCourses()
	{
		return catalog.getCourses();
	}
	
	public void addCourseToCatalog(Course newCourse)
	{
		catalog.addCourse(newCourse);
	}
	
	public void removeCourseFromCatalog(String courseID)
	{
		catalog.deleteCourse(courseID);
	}
	
	public Course getCourseFromCatalog(String courseID)
	{
		return new Course(catalog.getCourse(courseID));
	}
	
	public boolean setNumCredits(String courseID, int creds)
	{
		return catalog.editNumCredits(courseID, creds);
	}
	
	public double getNumCredits(String courseID) {
		return catalog.getNumCredits(courseID);
	}
	
	public boolean removeAvailability(String courseID, int season)
	{
		return catalog.removeAvailability(courseID, season);
	}
	
	public boolean addAvailability(String courseID, int season)
	{
		return catalog.addAvailability(courseID, season);
	}
	
	public boolean addCoursePrereq(String courseID, String prereq)
	{
		return catalog.addCoursePrereq(courseID, prereq);
	}
	
	public boolean removeCoursePrereq(String courseID, String prereq)
	{
		return catalog.removeCoursePrereq(courseID, prereq);
	}
	
	public boolean setCourseDescription(String courseID, String desc)
	{
		return catalog.editCourseDescription(courseID, desc);
	}
	
	public boolean setCourseNam(String courseID, String courseName)
	{
		return catalog.editCourseName(courseID, courseName);
	}
	
	public boolean changeCourseID(String courseID, String newID)
	{
		return catalog.changeCourseID(courseID, newID);
	}
	//
	//end catalog methods
	//
	

	
	
	
	//
	//
	//end catalog methods
	//
	
	//
	//Student Methods
	//
	//
	public ArrayList<String> getPlanNames()
	{
		if(!isAdmin && loggedIn)
		{
			return ((Student)presentUser).getPlanNames();
		}
		return null;
	}
	
	public Plan getPlan(String planName)
	{
		Student myStudent = null;
		if(!isAdmin && loggedIn)
		{
			myStudent = (Student)presentUser;
			return myStudent.getPlanWithName(planName);
		}
		else
		{
			//no soup for admins
			return null;
		}
	}
	
	public void addPlan(Plan newPlan)
	{
		Student myStudent = null;
		if(!isAdmin && loggedIn)
		{
			myStudent = (Student)presentUser;
			myStudent.addPlan(newPlan);
		}
	}	
	public double calculateOverallGPA(String planName)
	{
		//silly admin, GPAs are for kids
		if(isAdmin && loggedIn)
		{
			//admin does not have this functionality
			//throw exception
		}
		
		double gpa = 0;
		//both of these should be doubles
		double pointsEarned = 0;
		double creditsEarned = 0;
		
		Plan myPlan = ((Student)presentUser).getPlanWithName(planName);
		
		if(myPlan == null)
		{
			//plan with planName not found
			//throw Exception
		}
		
		ArrayList<Semester> mySemesters = myPlan.getSemesters();
		
		for(int i = 0; i != mySemesters.size(); i++)
		{
			Semester presentSemester = mySemesters.get(i);
			if(presentSemester.isPrevious())
			{
				pointsEarned += calculatePointsEarnedInSemester(presentSemester);
				creditsEarned += calculateCreditsInSemester(presentSemester);
			}
		}
		
		gpa = pointsEarned/creditsEarned;
		
		return gpa;
	}
	
	public double calculateSemesterGPA(String planName, int season, int year)
	{
		//silly admin, GPAs are for rabbits
		if(isAdmin && loggedIn)
		{
			//admin does not have this functionality
			//throw exception
		}
		if(loggedIn)
		{
			double gpa = 0;
			double coursesTaken = 0;
		
			Plan myPlan = ((Student)presentUser).getPlanWithName(planName);
		
			if(myPlan == null)
			{
				//plan with planName not found
				//throw Exception
			}
		
			Semester mySemester = myPlan.getSemester(season, year);
		
			if(mySemester == null)
			{
				//semester with season and year not found in plan planName
				//throw exception
			}
		
			ArrayList<CourseRecord> myCourses = mySemester.getCourseRecords();
			coursesTaken = myCourses.size();
			gpa = calculatePointsEarnedInSemester(mySemester)/calculateCreditsInSemester(mySemester);
		
			return gpa;
		}
		return 0;
	}
	
	private double calculateCreditsInSemester(Semester mySemester)
	{
		ArrayList<CourseRecord> myCourses = mySemester.getCourseRecords();
		int credits = 0;
		for(int i = 0; i != myCourses.size(); i++)
		{
			CourseRecord cr = myCourses.get(i);
//			if(cr.getGrade() != ProjectConstants.NO_GRADE)
//			{
				if(catalog.getCourse(cr.getCourseID()) != null)
				{
					credits += catalog.getCourse(cr.getCourseID()).getNumCreds();
				}
//			}
		}
		
		return credits;
	}
	
	private double calculatePointsEarnedInSemester(Semester mySemester)
	{
		ArrayList<CourseRecord> myCourses = mySemester.getCourseRecords();
		int points = 0;
		for(int i = 0; i != myCourses.size(); i++)
		{
			CourseRecord cr = myCourses.get(i);
			if(cr.getGrade() != ProjectConstants.NO_GRADE)
			{
				if(catalog.getCourse(cr.getCourseID()) != null)
				{
					double numCreds = catalog.getCourse(cr.getCourseID()).getNumCreds();
					int grade = gradeToInt(cr.getGrade());
					points += (grade*numCreds); 
				}
			}
		}
		
		return points;
	}
	
	private int gradeToInt(char grade)
	{
		if(grade == 'A') return 4;
		else if(grade == 'B') return 3;
		else if(grade == 'C') return 2;
		else if(grade == 'D') return 1;
		else return 0;
	}
	
	public ArrayList<Semester> getSemesters(String planName)
	{
		Student myStudent = null;
		if(!isAdmin && loggedIn)
		{
			myStudent = (Student)presentUser;
			return myStudent.getSemesters(planName);
		}
		else
		{
			return null;
		}
	}
	
	public boolean changePlanName(String planName, String newName)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.changePlanName(planName, newName);
		}
		else
		{
			return false;
		}
	}

	public boolean removeSemesterFromPlan(String planName, int season, int year)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.removeSemesterFromPlan(planName, season, year);
		}
		else
		{
			return false;
		}
	}

	public boolean addSemesterToPlan(String planName, Semester newSem)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.addSemesterToPlan(planName, newSem);
		}
		else
		{
			return false;
		}
	}

	public ArrayList<CourseRecord> getCourseRecords(String planName, int season, int year)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.getCourseRecords(planName, season, year);
			
		}
		else
		{
			return null;
		}
	}
	
	public CourseRecord getCourseRecord(String planName, int season, int year, String courseID)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.getCourseRecord(planName, season, year, courseID);
		}
		else
		{
			return null;
		}
	}
	
	public ArrayList<String> getCourseIDs(String planName, int season, int year)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.getCourseIDs(planName, season, year);
		}
		else
		{
			return null;
		}
	}
	
	public ArrayList<String> getAllSemesterTitlesInPlan(String planName)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.getAllSemesterTitlesInPlan(planName);
		}
		else
		{
			return null;
		}
	}
	 
	public boolean changeCourseRecordGrade(String planName, int season, int year, String courseID, char grade)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.changeCourseRecordGrade(planName, season, year, courseID, grade);
		}
		else
		{
			return false;
		}
	}
	
	public boolean changeCourseRecordNotes(String planName, int season, int year, String courseID, String notes)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.changeCourseRecordNotes(planName, season, year, courseID, notes);
		}
		else
		{
			return false;
		}
	}
	
	public boolean getSemesterPrevious(String planName, int season, int year)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.getSemesterPrevious(planName, season, year);
		}
		else
		{
			//exception not false
			return false;
		}
	}
	
	public int addCourseRecord(String planName, int season, int year, CourseRecord newCR)
	{
		if(!isAdmin && loggedIn)
		{
			//check for credit cap and override
			double courseCreds = catalog.getCourse(newCR.getCourseID()).getNumCreds();
			
			Student myStudent = (Student)presentUser;
			Semester mySem = myStudent.getSemester(planName, season, year);
			if((calculateCreditsInSemester(mySem)+courseCreds) <= mySem.getMaxCredits())
			{
				if (myStudent.getCourseRecord(planName, season, year, newCR.getCourseID()) != null) {
					return -1;
				} else if (myStudent.getCourseRecord(planName, season, year, newCR.getCourseID() + "H") != null) {
					return -1;
				} else if (myStudent.getCourseRecord(planName, season, year, newCR.getCourseID().substring(0, newCR.getCourseID().length() - 1)) != null) {
					return -1;
				} else if (!myStudent.addCourseRecord(planName, season, year, newCR)) {
					return -2;
				} else {
					return 1;
				}
			}
			
			return ((mySem.getMaxCredits()) * -1);
		}
		
		return -2;
			
			//1 = okay
			//-1 = dup course
			//-2 = other issue
			//neg number = credit limit (ex -19)
	}
	
	public boolean setSemesterOverridden(String planName, int season, int year, boolean overridden)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.setSemesterOverridden(planName, season, year, overridden);
		}
		else
		{
			return false;
		}
	}
	
	public boolean removeCourseRecord(String planName, int season, int year, String courseID)
	{
		if(!isAdmin && loggedIn)
		{
			Student myStudent = (Student)presentUser;
			return myStudent.removeCourseRecord(planName, season, year, courseID);
		}
		else
		{
			return false;
		}
	}
	
	public boolean isAdmin()
	{
		return isAdmin;
	}
	
	public boolean isLoggedIn()
	{
		return loggedIn;
	}
	//
	// End Student Methods
	//
	//end Student methods
	//
	
	


	public static void main(String[] args)
	{
		VirtualAdvisor myVA = new VirtualAdvisor();
		
		System.out.println(myVA.analyseFullPlanCompleteDegree("StutskyPlan"));
		
		/*
		System.out.println("Overall gpa: " + myVA.calculateOverallGPA("StutskyPlan"));
		ArrayList<Semester> mySem = myVA.getSemesters("StutskyPlan");
		for(Semester sem : mySem)
		{
			System.out.println(sem.getYear() + " " + sem.getSeason());
			System.out.println(myVA.calculateSemesterGPA("StutskyPlan", sem.getSeason(), sem.getYear()));
			System.out.println();
		}
		
		System.out.println(myVA.addCourseRecord("StutskyPlan", ProjectConstants.SPRING, 2011, new CourseRecord("CMSC 411")));
		
		System.out.println(myVA.getPlan("StutskyPlan"));
		
		System.out.println(myVA.addCourseRecord("StutskyPlan", ProjectConstants.SPRING, 2011, new CourseRecord("CMSC 421")));
		
		System.out.println(myVA.getPlan("StutskyPlan"));
		*/
	}

	
	//
	//degree methods
	//
	public String[] getDegreeNames() {
		String[] degrees = new String[this.degrees.size()];
		for (int i = 0; i < degrees.length; i++) {
			degrees[i] = this.degrees.get(i).name;
		}
		
		return degrees;
	}
	
	/**
	 * getCategories
	 * @param degreeSelected
	 * @return
	 */
	public String[] getCategories(String degreeSelected) 
	{
		for (Degree d : degrees) {
			if (d.name.equals(degreeSelected)) {
				return d.listSections();
			}
		}
		
		return null;
	}

	/**
	 * getCourseSet
	 * @param degreeSelected
	 * @param categorySelected
	 * @return
	 */
	public String[] getCourseSet(String degreeSelected, String categorySelected) {
		for (Degree d : degrees) {
			if (d.name.equals(degreeSelected)) {
				return d.getAllCoursesInSection(categorySelected);
			}
		}
		
		return null;
	}

	//Don't return courses the user can't take again (already taken 3 times)
	public String[] getAvailableCourses(String degreeSelected, String categorySelected, String planName) {
		String[] fullSet = getCourseSet(degreeSelected, categorySelected);
		ArrayList<String> availableCourses = new ArrayList<String>();
		
		for (String course : fullSet) {
			if (!hasCompletedCourseThreeTimes(planName, course)) {
				availableCourses.add(course);
			}
		}
		
		if (availableCourses.size() < fullSet.length){
			fullSet = new String[availableCourses.size()];
			for (int i = 0; i < fullSet.length; i++) {
				fullSet[i] = availableCourses.get(i);
			}
		}

		return fullSet;
	}
	
	public static void saveData() throws IOException, ClassNotFoundException {
		RequestInterpreter.saveUsers(users);
		RequestInterpreter.saveCatalog(catalog.getCourses());
		RequestInterpreter.saveCurriculum(degrees);
	}
	
	public static void saveUser(String username) throws IOException, ClassNotFoundException {
		for (User u : users) {
			if (u.username.equals(username)) {
				RequestInterpreter.saveUsers(users);
				return;
			}
		}
	}
}